/****************************************************************************
 * (c) 2001 StreamBox Inc.  http://www.streambox.com/ 
 *
 * Division: Moscow Research Division
 * Project:  Tidy Scaling (video compression project)
 *
 * Contents: Filter-based scaling functions. Only ^2 scaling factor allowed.
 *           File contains 10-item fast filter implemntation.
 *
 * History:  06-Sep-2001 - Created by Smirnov K. from source code of Dmitriy Vatolin
 ****************************************************************************/
/**
 * \file scale_msk_f16.c
 *  File contains 16-item filter implemntation. 
 *  Filter coeficients {-17,-381,162,861,-591,-1719,2084,7793,
 *					7793,2084, -1719, -591,861, 162, -381, -17}
 *  Functions:
 *  void ScaleLineUpX2Filter16() 
 *  void ScaleLineDownX2Filter16()
 */

#include "Scale_msk.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/*============================= ScaleLineUpX2Filter16 ==============================*/
/**
 * Scale UP 1D Channel (one line) by 16-items filter. 
 *
 * \param in          [IN]  - pointer to input one dimensional channels
 * \param out         [OUT] - pointer to output one dimensional channels
 * \param l           [IN]  - in-buffer length
 * \retval - none
 */

void ScaleLineUpX2Filter16( int *in, int *out, int l )
{
	int i,d,c,c2,c3,c4,q, d_nf2;
    d=l>>1;

    for(i=0;i<l;i++) out[i]=0; 
    //memset(out,0,l*4);

    c =in[0];
    c2=in[1];
    c3=in[2];
    c4=in[3];

    out[0]+=  7793*c + 2084*c2 -  591*c3 +  162*c4;
    out[1]+=  2084*c + 7793*c2 - 1719*c3 +  861*c4;
    out[2]+= -1719*c + 7793*c2 + 2084*c3 -  591*c4;
    out[3]+= - 591*c + 2084*c2 + 7793*c3 - 1719*c4;
    out[4]+=   861*c - 1719*c2 + 7793*c3 + 2084*c4;
    out[5]+=   162*c -  591*c2 + 2084*c3 + 7793*c4;
    out[6]+= - 381*c +  861*c2 - 1719*c3 + 7793*c4;
    out[7]+= -  17*c +  162*c2 -  591*c3 + 2084*c4;
    out[8]+=         -  381*c2 +  861*c3 - 1719*c4;
    out[9]+=         -   17*c2 +  162*c3 -  591*c4;
    out[10]+=                  -  381*c3 +  861*c4;
    out[11]+=                  -   17*c3 +  162*c4;
    out[12]+=                            -  381*c4;
    out[13]+=                            -   17*c4;

    d_nf2=d-3;
    for(i=4,q=0; i<d_nf2; i++,q+=2) 
	{
        c=in[i];
		out[q   ]+=-17*c;
		out[q+15]+=-17*c;
		out[q+1 ]+=-381*c;
		out[q+14]+=-381*c;
		out[q+2 ]+=162*c;
		out[q+13]+=162*c;
		out[q+3 ]+=861*c;
		out[q+12]+=861*c;
		out[q+4 ]+=-591*c;
		out[q+11]+=-591*c;
		out[q+5 ]+=-1719*c;
		out[q+10]+=-1719*c;
		out[q+6 ]+=2084*c;
		out[q+9 ]+=2084*c;
		out[q+7 ]+=7793*c;
		out[q+8 ]+=7793*c;
	}

    c =in[d-1]; 
	c2=in[d-1];
	c3 = in[d-2];
	c4 = in[d-3];
    q=d*2;
    out[q-1]+=  7793*c + 2084*c2 -  591*c3 +  162*c4;
    out[q-2]+=  2084*c + 7793*c2 - 1719*c3 +  861*c4;
    out[q-3]+= -1719*c + 7793*c2 + 2084*c3 -  591*c4;
    out[q-4]+= - 591*c + 2084*c2 + 7793*c3 - 1719*c4;
    out[q-5]+=   861*c - 1719*c2 + 7793*c3 + 2084*c4;
    out[q-6]+=   162*c -  591*c2 + 2084*c3 + 7793*c4;
    out[q-7]+= - 381*c +  861*c2 - 1719*c3 + 7793*c4;
    out[q-8]+= -  17*c +  162*c2 -  591*c3 + 2084*c4;
    out[q-9]+=         -  381*c2 +  861*c3 - 1719*c4;
    out[q-10]+=        -   17*c2 +  162*c3 -  591*c4;
    out[q-11]+=                  -  381*c3 +  861*c4;
    out[q-12]+=                  -   17*c3 +  162*c4;
    out[q-13]+=                            -  381*c4;
    out[q-14]+=                            -   17*c4;

    //////////////////// Dividing filter circles
    out[0]   = (out[0] + 4715)/9431;
    out[q-1]= (out[q-1] + 4715)/9431;

    out[1]   = (out[1] + 4319)/8638;
    out[q-2]= (out[q-2] + 4319)/8638;

    out[2]   = (out[2] + 3856)/7712;
    out[q-3]= (out[q-3] + 3856)/7712;

    out[3]   = (out[3] + 4023)/8047;
    out[q-4]= (out[q-4] + 4023)/8047;

    out[4]   = (out[4] + 4286)/8573;
    out[q-5]= (out[q-5] + 4286)/8573;

    out[5]   = (out[5] + 4104)/8209;
    out[q-6]= (out[q-6] + 4104)/8209;
    
	d_nf2=l-6-4; // l-right-spare
    for(i=6;i<d_nf2;i+=4)
    {
       	out[i  ]=(out[i  ]+4096)>>13; 
       	out[i+1]=(out[i+1]+4096)>>13;
       	out[i+2]=(out[i+2]+4096)>>13;
       	out[i+3]=(out[i+3]+4096)>>13;
    }
    for(;i<d_nf2+4;i++)
       	out[i]=(out[i]+4096)>>13; 
}
/*============================= ScaleLineDownX2Filter16 ==============================*/
/**
 * Scale DOWN 1D Channel (one line) by 16-items filter. 
 *
 * \param in          [IN]  - pointer to input one dimensional channels
 * \param out         [OUT] - pointer to output one dimensional channels
 * \param l           [IN]  - in-buffer length
 * \retval - none
 */
void ScaleLineDownX2Filter16(int *in, int *out, int l)
{
	int i,i1,d,d_max;
    d=l>>1;

    out[0]= ( 7793*in[0] + 2084*in[1] - 1719*in[2] - 591*in[3] + 861*in[4]
			  +162*in[5] - 381*in[6]  - 17*in[7] + 4096 )>>13;
    
	out[1]= ( 2084*(in[0]+in[3]) + 7793*(in[1]+in[2]) - 1719*in[4] - 591*in[5] 
			  + 861*in[6] + 162*in[7] - 381*in[8] - 17*in[9] + 9034 )/18069;
    
	out[2]= ( -591*(in[0]+in[7]) - 1719*(in[1]+in[6]) + 2084*(in[2] + in[5]) 
			  + 7793*(in[3] + in[4]) + 861*in[8] + 162*in[9] - 381*in[10] 
			  - 17*in[11] + 7879 )/15759;
    
	out[3]= ( 162*(in[0]+in[11]) + 861*(in[1]+in[10]) - 591*(in[2] + in[6]) 
			 - 1719*(in[3] + in[8]) + 2084*(in[4]+in[7]) + 7793*(in[5]+in[6]) 
			 - 381*in[12] - 17*in[13] + 8391 )/16782;
                                                                //
    d_max=d-3;
	for(i=4,i1=0; i<d_max;i++, i1+=2)
	{
        out[i]=( 7793*(in[i1+7]+in[i1+8 ]) 
               + 2084*(in[i1+6]+in[i1+9 ])
               - 1719*(in[i1+5]+in[i1+10])
               -  591*(in[i1+4]+in[i1+11])
               +  861*(in[i1+3]+in[i1+12])
               +  162*(in[i1+2]+in[i1+13]) 
               -  381*(in[i1+1]+in[i1+14]) 
               -   17*(in[i1  ]+in[i1+15]) +8192)>>14;
    }

    i1=(d<<1);

	out[d-1]= ( 2084*(in[i1-1]+in[i1-4]) + 7793*(in[i1-2]+in[i1-3]) - 1719*in[i1-5] - 591*in[i1-6] 
			  + 861*in[i1-7] + 162*in[i1-8] - 381*in[i1-9] - 17*in[i1-10] +9034 )/18069;
    
	out[d-2]= ( -591*(in[i1-1]+in[i1-8]) - 1719*(in[i1-2]+in[i1-7]) + 2084*(in[i1-3] + in[i1-6]) 
			  + 7793*(in[i1-4] + in[i1-5]) + 861*in[i1-9] + 162*in[i1-10] - 381*in[i1-11] 
			  - 17*in[i1-12] + 7879 )/15759;
    
	out[d-3]= ( 162*(in[i1-1]+in[i1-12]) + 861*(in[i1-2]+in[i1-11]) - 591*(in[i1-3] + in[i1-7]) 
			 - 1719*(in[i1-4] + in[i1-9]) + 2084*(in[i1-5]+in[i1-8]) + 7793*(in[i1-6]+in[i1-7]) 
			 - 381*in[i1-13] - 17*in[i1-14] + 8391 )/16782;

}                                                                             //

